import os
from typing import List, Dict
import requests
from bs4 import BeautifulSoup
import time
import random
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager


class AigeiCrawler:
    def __init__(self):
        self.base_url = "https://www.aigei.com"
        self.search_url = f"{self.base_url}/s"
        self.headers = {
            'User-Agent': (
                'Mozilla/5.0 (Windows NT 10.0; Win64; x64) '
                'AppleWebKit/537.36 (KHTML, like Gecko) '
                'Chrome/91.0.4472.124 Safari/537.36'
            ),
            'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
            'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
            'Accept-Encoding': 'gzip, deflate, br',
            'Connection': 'keep-alive',
            'Upgrade-Insecure-Requests': '1'
        }
        # 初始化Selenium WebDriver
        options = webdriver.ChromeOptions()
        options.add_argument('--headless')  # 无头模式
        options.add_argument('--disable-gpu')
        options.add_argument('--no-sandbox')
        options.add_argument('--disable-dev-shm-usage')
        options.add_argument(f'user-agent={self.headers["User-Agent"]}')
        self.driver = webdriver.Chrome(
            service=Service(ChromeDriverManager().install()),
            options=options
        )
        
    def __del__(self):
        """析构函数，确保关闭浏览器"""
        if hasattr(self, 'driver'):
            self.driver.quit()
        
    def search_sound_effects(self, keyword: str) -> List[Dict]:
        """
        搜索音效资源
        :param keyword: 搜索关键词
        :return: 搜索结果列表
        """
        # 构建完整的搜索URL
        search_url = f"{self.search_url}?q={keyword}&dim=sound_effect"
        print(f"正在访问URL: {search_url}")
        
        try:
            # 使用Selenium访问页面
            self.driver.get(search_url)
            
            # 等待页面加载（最多等待10秒）
            print("等待页面加载...")
            WebDriverWait(self.driver, 10).until(
                EC.presence_of_element_located((By.CLASS_NAME, "item-view-url"))
            )
            
            # 添加随机延迟
            time.sleep(random.uniform(2, 4))
            
            # 获取页面源代码
            html_content = self.driver.page_source
            print(f"获取到页面内容，长度: {len(html_content)} 字节")
            
            # 保存响应内容到文件（用于调试）
            with open('response.html', 'w', encoding='utf-8') as f:
                f.write(html_content)
            print("已将响应内容保存到 response.html")
            
            # 解析页面内容
            return self.parse_search_results(html_content)
            
        except Exception as e:
            print(f"抓取过程中出现错误: {e}")
            return []
        
    def parse_search_results(self, html_content: str) -> List[Dict]:
        """
        解析搜索结果页面
        :param html_content: 页面HTML内容
        :return: 解析后的音频资源列表
        """
        soup = BeautifulSoup(html_content, 'html.parser')
        results = []
        
        try:
            # 打印页面标题
            print(f"页面标题: {soup.title.string if soup.title else '无标题'}")
            
            # 查找所有音频项
            audio_items = soup.find_all('div', class_='item-view-url')
            print(f"找到 {len(audio_items)} 个音频项")
            
            for item in audio_items:
                try:
                    # 获取标题和链接
                    link_elem = item.find('a')
                    if not link_elem:
                        continue
                    
                    title = link_elem.get('title', '')
                    item_url = link_elem.get('href', '')
                    if item_url.startswith('/'):
                        item_url = self.base_url + item_url
                    
                    # 获取音频时长和下载链接
                    parent_div = item.find_parent('div', class_='unit-info-row')
                    if parent_div:
                        # 获取音频时长
                        duration_elem = parent_div.find(
                            'div',
                            class_=lambda x: x and 'duration' in x.lower()
                        )
                        duration = duration_elem.text.strip() if duration_elem else "未知"
                        
                        # 获取下载链接
                        download_elem = parent_div.find(
                            'a',
                            class_=lambda x: x and 'download' in x.lower()
                        )
                        if download_elem:
                            download_url = download_elem.get('href', '')
                            if download_url.startswith('/'):
                                download_url = self.base_url + download_url
                        else:
                            download_url = item_url
                    else:
                        duration = "未知"
                        download_url = item_url
                    
                    results.append({
                        'title': title,
                        'duration': duration,
                        'url': download_url
                    })
                    print(f"已解析音频: {title}")
                    
                except Exception as e:
                    print(f"解析音频项时出现错误: {e}")
                    continue
            
        except Exception as e:
            print(f"解析页面时出现错误: {e}")
        
        return results

    def download_audio(self, audio_info: Dict, save_dir: str) -> bool:
        """
        下载音频文件
        :param audio_info: 音频信息字典
        :param save_dir: 保存目录
        :return: 是否下载成功
        """
        try:
            # 创建保存目录
            os.makedirs(save_dir, exist_ok=True)
            
            # 构建文件名（使用标题作为文件名）
            filename = f"{audio_info['title']}.mp3"  # 假设文件格式为mp3
            # 替换文件名中的非法字符
            filename = "".join(c for c in filename if c.isalnum() or c in (' ', '-', '_', '.'))
            filepath = os.path.join(save_dir, filename)
            
            # 下载文件
            print(f"正在下载: {audio_info['title']}")
            response = requests.get(audio_info['url'], headers=self.headers, stream=True)
            response.raise_for_status()
            
            # 写入文件
            with open(filepath, 'wb') as f:
                for chunk in response.iter_content(chunk_size=8192):
                    if chunk:
                        f.write(chunk)
            
            print(f"下载完成: {filepath}")
            return True
            
        except Exception as e:
            print(f"下载音频时出现错误: {e}")
            return False


def main():
    crawler = AigeiCrawler()
    keyword = "鼓掌"
    save_dir = "downloads"
    
    # 搜索音频
    results = crawler.search_sound_effects(keyword)
    print(f"\n找到 {len(results)} 个搜索结果:")
    
    # 下载前5个音频文件
    for i, audio in enumerate(results[:5]):
        print(f"\n下载第 {i+1} 个音频:")
        print(f"标题: {audio['title']}")
        print(f"时长: {audio['duration']}")
        crawler.download_audio(audio, save_dir)


if __name__ == "__main__":
    main() 